#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include "../comm/Log.hpp"
#include "../comm/util.hpp"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <wait.h>


namespace complierNs {
    using namespace utilNs;
    using namespace logNs;
    
    class Complier {
    public :
        static bool Complie(const std::string& file_name) {
            // 先获取完整的可执行程序的路径
            std::string code_file = PathUtil::Src(file_name);
            
            // 再次获取编译失败后错误信息要保存到的文件完整路径
            std::string complie_err = PathUtil::ComplieErr(file_name);
            // std::cout << "Complie:: complie_err== " << complie_err << std::endl;
            // 打开这个文件
            umask(0);
            int complie_err_fd = open(complie_err.c_str(), O_CREAT | O_WRONLY, 0644);
            if (complie_err_fd < 0) {
                // 打开文件失败
                LOG(Error) << "内部错误, 打开文件失败" << std::endl;
                return false;
            }

            pid_t id = fork();
            if (id < 0) {
                // 创建子进程失败
                close(complie_err_fd);
                LOG(Error) << "内部错误, 创建子进程失败" << std::endl;
                return false;
            } else if (id == 0) {
                // 子进程
                dup2(complie_err_fd, 2); // 将标准错误重定向到complie_err_fd

                // 使用程序替换编译程序
                execlp("g++", "g++", "-o", PathUtil::Exe(file_name).c_str(), code_file.c_str(), "-D", "COMPLIE_OLINE", "-std=c++14", nullptr);
                // 执行程序替换失败
                LOG(Waring) << "进程程序替换失败" << std::endl;
                exit(-1);
            } else {
                // 父进程
                close(complie_err_fd);
                // 等待子进程
                waitpid(id, nullptr, 0);
                // 判断是否编译成功，只需要判断可执行程序文件是否存在
                if (FileUtil::IsExistFile(PathUtil::Exe(file_name))) {
                    // 编译运行成功
                    LOG(Debug) << "编译运行成功, 成功形成可执行程序" << std::endl;
                    return true;
                }
            }
            LOG(Debug) << "编译出错, 没有形成可执行程序" << std::endl;
            return false;
        }
    private :
    };
};